﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SHZY.BaseData.Entitys.Entity;
using SHZY.Business.Entitys;
using SHZY.Business.Interfaces;
using SHZY.Common.Core.Manager;
using SHZY.Common.Enum;
using SHZY.DependencyInjection;
using SHZY.DynamicApiController;
using SHZY.FriendlyException;
using SHZY.Message.Interfaces.Message;
using SHZY.Systems.Entitys.Permission;
using SHZY.Systems.Entitys.System;
using SHZY.Systems.Interfaces.System;
using Spire.Doc.Interface;
using SqlSugar;

namespace SHZY.Business
{
    public class OverdueHandleService: IOverdueHandleService, IDynamicApiController, ITransient
    {
        /// <summary>
        /// 服务基础仓储.
        /// </summary>
        private readonly ISqlSugarRepository<QmsBusiInspectionlotEntity> _repository;

        /// <summary>
        /// 用户管理.
        /// </summary>
        private readonly IUserManager _userManager;

        private readonly ITenant _db;

        private readonly IMessageService _messageService;

        public OverdueHandleService(ISqlSugarRepository<QmsBusiInspectionlotEntity> repository,
            ISqlSugarClient context,
            IUserManager userManager,
            IMessageService messageService) 
        {
            _repository = repository;
            _userManager = userManager;
            _db = context.AsTenant();
            _messageService = messageService;
        }

        /// <summary>
        /// 来料检验逾期处理.
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task GenerateInspectionOverdue()
        { 
            // 查询未逾期，未过账检验批数据
            var lotList = await _repository.Context.Queryable<QmsBusiInspectionlotEntity>()
                .Where(x => x.Status != 3 && (x.Overdue == null || x.Overdue != 2) && x.EnabledMark == 1 && x.DeleteMark == null).ToListAsync();
            // 查询未确认，未逾期报检单数据
            var insFormList = await _repository.Context.Queryable<QmsBusiInspectionEntity>()
                .Where(x => x.Status == 0 && (x.Overdue == null || x.Overdue != 2) && x.EnabledMark == 1 && x.DeleteMark == null).ToListAsync();
            //获取逾期设置信息
            var setingList = await _repository.Context.Queryable<QmsBaseOverduesettingEntity>()
                .Where(x => x.DeleteMark == null && x.EnabledMark == 1).ToListAsync();
            var lotSettingList = setingList.Where(w => w.Type == "2").ToList();
            var inspectionSettingList = setingList.Where(w => w.Type == "1").ToList();
            // 获取字典项业务信息
            var dic = _repository.Context.Queryable<DictionaryDataEntity>().Where(w => w.DictionaryTypeId.Equals("459581510966602757")).ToList();

            var now = DateTime.Now;

            #region 来料检验逾期处理
            List<QmsBusiInspectionlotEntity> List1 = new List<QmsBusiInspectionlotEntity>();
            foreach (var item in lotList)
            {
                var old = DateTime.Parse(item.CreatorTime.ToString());
                var _info = TimeUnit(lotSettingList, now, old);
                if (_info != null && !_info.Status.Equals(item.Overdue == null ? "0" : item.Overdue.ToString()))
                {
                    item.Overdue = Convert.ToInt32(_info.Status);
                    string _overdueDec = item.Overdue == 1 ? "即将逾期" : "已逾期";
                    string _type = dic.Find(f => f.EnCode.Equals(_info.Type)).FullName;
                    string toUserIds = String.Empty;
                    if (item.Overdue == 1)
                    {
                        var userInfo = await _repository.Context.Queryable<UserEntity>().Where(it => it.Account == item.EmployeeCode).FirstAsync();
                        toUserIds = userInfo.Id;
                    }
                    else
                    {
                        toUserIds = _info.RecipientList;
                    }
                    List1.Add(item);
                    // 推送消息
                    SendMessageEvent(item.Code, _overdueDec, _type, toUserIds, false);
                }
            }
            if (List1.Count > 0)
            {
                var isOk = _repository.Context.Updateable(List1).UpdateColumns(x => new { x.Overdue }).ExecuteCommand();
                if (isOk <= 0)
                    throw Oops.Oh(ErrorCode.COM1002);
            }
            #endregion

            #region 报检单逾期处理
            List<QmsBusiInspectionEntity> List2 = new List<QmsBusiInspectionEntity>();
            foreach (var item in insFormList)
            {
                var old = DateTime.Parse(item.CreatorTime.ToString());
                var _info = TimeUnit(inspectionSettingList, now, old);
                if (_info != null && !_info.Status.Equals(item.Overdue == null ? "0" : item.Overdue.ToString()))
                {
                    item.Overdue = Convert.ToInt32(_info.Status);
                    string _overdueDec = item.Overdue == 1 ? "即将逾期" : "已逾期";
                    string _type = dic.Find(f => f.EnCode.Equals(_info.Type)).FullName;
                    string toUserIds = String.Empty;
                    if (item.Overdue == 1)
                    {
                        toUserIds = item.CreatorUserId.ToString();
                    }
                    else
                    {
                        toUserIds = _info.RecipientList;
                    }
                    List2.Add(item);
                    SendMessageEvent(item.Code, _overdueDec, _type, toUserIds, false);
                }
            }
            if (List2.Count > 0)
            {
                var isOk = _repository.Context.Updateable(List2).UpdateColumns(x => new { x.Overdue }).ExecuteCommand();
                if (isOk <= 0)
                    throw Oops.Oh(ErrorCode.COM1002);
            }
            #endregion
        }

        /// <summary>
        /// 制程检验逾期处理.
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task GenerateIPQCInspectionOverdue()
        {
            // 查询未逾期，未过账检验批数据
            var lotList = await _repository.Context.Queryable<QmsBusiIpqcinspectionlotEntity>()
                .Where(x => x.Status != 3 && (x.Overdue == null || x.Overdue != 2) && x.EnabledMark == 1 && x.DeleteMark == null).ToListAsync();
            // 查询未确认，未逾期报检单数据
            var insFormList = await _repository.Context.Queryable<QmsBusiIpqcinspectionEntity>()
                .Where(x => x.Status == 0 && (x.Overdue == null || x.Overdue != 2) && x.EnabledMark == 1 && x.DeleteMark == null).ToListAsync();
            //获取逾期设置信息
            var setingList = await _repository.Context.Queryable<QmsBaseOverduesettingEntity>()
                .Where(x => x.DeleteMark == null && x.EnabledMark == 1).ToListAsync();
            var lotSettingList = setingList.Where(w => w.Type == "3").ToList();
            var inspectionSettingList = setingList.Where(w => w.Type == "2").ToList();
            // 获取字典项业务信息
            var dic = _repository.Context.Queryable<DictionaryDataEntity>().Where(w => w.DictionaryTypeId.Equals("459581510966602757")).ToList();

            var now = DateTime.Now;

            #region 制程检验逾期处理
            List<QmsBusiIpqcinspectionlotEntity> list1 = new List<QmsBusiIpqcinspectionlotEntity>();
            foreach (var item in lotList)
            {
                var old = DateTime.Parse(item.CreatorTime.ToString());
                var _info = TimeUnit(lotSettingList, now, old);
                if (_info != null && !_info.Status.Equals(item.Overdue == null ? "0" : item.Overdue.ToString()))
                {
                    item.Overdue = Convert.ToInt32(_info.Status);
                    string _overdueDec = item.Overdue == 1 ? "即将逾期" : "已逾期";
                    string _type = dic.Find(f => f.EnCode.Equals(_info.Type)).FullName;
                    string toUserIds = String.Empty;
                    if (item.Overdue == 1)
                    {
                        var userInfo = await _repository.Context.Queryable<UserEntity>().Where(it => it.Account == item.EmployeeCode).FirstAsync();
                        toUserIds = userInfo.Id;
                    }
                    else
                    {
                        toUserIds = _info.RecipientList;
                    }
                    list1.Add(item);
                    // 推送消息
                    SendMessageEvent(item.Code, _overdueDec, _type, toUserIds, false);
                }
            }
            if (list1.Count > 0)
            {
                var isOk = _repository.Context.Updateable(list1).UpdateColumns(x => new { x.Overdue }).ExecuteCommand();
                if (isOk <= 0)
                    throw Oops.Oh(ErrorCode.COM1002);
            }
            #endregion

            #region 报检单逾期处理
            List<QmsBusiIpqcinspectionEntity> list2 = new List<QmsBusiIpqcinspectionEntity>();
            foreach (var item in insFormList)
            {
                var old = DateTime.Parse(item.CreatorTime.ToString());
                var _info = TimeUnit(inspectionSettingList, now, old);
                if (_info != null && !_info.Status.Equals(item.Overdue == null ? "0" : item.Overdue.ToString()))
                {
                    item.Overdue = Convert.ToInt32(_info.Status);
                    string _overdueDec = item.Overdue == 1 ? "即将逾期" : "已逾期";
                    string _type = dic.Find(f => f.EnCode.Equals(_info.Type)).FullName;
                    string toUserIds = String.Empty;
                    if (item.Overdue == 1)
                    {
                        toUserIds = item.CreatorUserId.ToString();
                    }
                    else
                    {
                        toUserIds = _info.RecipientList;
                    }
                    list2.Add(item);

                    SendMessageEvent(item.Code, _overdueDec, _type, toUserIds, false);
                }
            }
            if (list2.Count > 0)
            {
                var isOk = _repository.Context.Updateable(list2).UpdateColumns(x => new { x.Overdue }).ExecuteCommand();
                if (isOk <= 0)
                    throw Oops.Oh(ErrorCode.COM1002);
            }
            #endregion
        }

        #region PrivateMethod

        /// <summary>
        ///  逾期判定.
        /// </summary>
        /// <param name="lists"></param>
        /// <param name="nowDate"></param>
        /// <param name="createTime"></param>
        /// <returns></returns>
        private QmsBaseOverduesettingEntity TimeUnit(List<QmsBaseOverduesettingEntity> lists, DateTime nowDate, DateTime createTime)
        {
            if (lists != null && lists.Count > 0)
            {
                // day判断
                var d = (nowDate - createTime).TotalDays;
                var d_info = lists.Where(w => w.TimeUnit == "day" && d >= w.MinValue && d <= w.MaxValue).FirstOrDefault();
                if (d_info != null) return d_info;
                //if (d_info != null) return Convert.ToInt32(d_info.Status);
                // hour比较
                var h = (nowDate - createTime).TotalHours;
                var h_info = lists.Where(w => w.TimeUnit == "hour" && h >= w.MinValue && h <= w.MaxValue).FirstOrDefault();
                if (h_info != null) return h_info;
                // 分钟比较
                var m = (nowDate - createTime).TotalMinutes;
                var m_info = lists.Where(w => w.TimeUnit == "minute" && m >= w.MinValue && m <= w.MaxValue).FirstOrDefault();
                if (m_info != null) return m_info;
                // 秒比较
                var s = (nowDate - createTime).TotalSeconds;
                var s_info = lists.Where(w => w.TimeUnit == "second" && s >= w.MinValue && s <= w.MaxValue).FirstOrDefault();
                if (s_info != null) return s_info;
            }

            return null;
        }

        /// <summary>
        /// 逾期消息推送.
        /// </summary>
        /// <param name="Code">检验批号</param>
        /// <param name="overdueDesc">是否逾期</param>
        /// <param name="Type">业务类型</param>
        /// <param name="toUserIds">消息推送人</param>
        /// <param name="isLogin">是否登录</param>
        private void SendMessageEvent(string Code, string overdueDesc, string Type, string toUserIds, bool isLogin = true)
        { 
            JArray jArray = new JArray();
            JObject jObject = new JObject();
            jObject.Add("F_Code", Code);
            jObject.Add("F_Type",Type);
            jObject.Add("F_Overdue", overdueDesc);
            jObject.Add("userName", isLogin ? _userManager.RealName : "system");
            jObject.Add("date", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            jArray.Add(jObject);
            _messageService.AddMessageEvent("overdue", toUserIds, jArray.ToString(), null, isLogin);
        }

        #endregion
    }
}
